package com.hxgz.steel.util;


import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.w3c.dom.Entity;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.transform.OutputKeys;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;
import java.io.ByteArrayInputStream;
import java.io.InputStream;
import java.io.StringWriter;
import java.util.*;

/*微信支付工具类，xml转map，map转xml，生成签名*/
public class WXPayUtil {

  /**
   * XML格式字符串转换为Map
   *
   * @param strXML XML字符串
   * @return XML数据转换后的Map
   */
  public static Map<String, String> xmlToMap(String strXML) throws Exception {
    try {
      Map<String, String> data = new HashMap<String, String>();
      DocumentBuilder documentBuilder = WXPayXmlUtil.newDocumentBuilder();
      InputStream stream = new ByteArrayInputStream(strXML.getBytes("UTF-8"));
      org.w3c.dom.Document doc = documentBuilder.parse(stream);
      doc.getDocumentElement().normalize();
      NodeList nodeList = doc.getDocumentElement().getChildNodes();
      for (int idx = 0; idx < nodeList.getLength(); ++idx) {
        Node node = nodeList.item(idx);
        if (node.getNodeType() == Node.ELEMENT_NODE) {
          org.w3c.dom.Element element = (org.w3c.dom.Element) node;
          data.put(element.getNodeName(), element.getTextContent());
        }
      }
      try {
        stream.close();
      } catch (Exception ex) {
        // do nothing
      }
      return data;
    } catch (Exception ex) {
      WXPayUtil.getLogger()
          .warn("Invalid XML, can not convert to map. Error message: {}. XML content: {}",
              ex.getMessage(), strXML);
      throw ex;
    }

  }

  /**
   * 将Map转换为XML格式的字符串
   *
   * @param data Map类型数据
   * @return XML格式的字符串
   */
  public static String mapToXml(Map<String, String> data) throws Exception {
    org.w3c.dom.Document document = WXPayXmlUtil.newDocument();
    org.w3c.dom.Element root = document.createElement("xml");
    document.appendChild(root);
    for (String key : data.keySet()) {
      String value = data.get(key);
      if (value == null) {
        value = "";
      }
      value = value.trim();
      org.w3c.dom.Element filed = document.createElement(key);
      filed.appendChild(document.createTextNode(value));
      root.appendChild(filed);
    }
    TransformerFactory tf = TransformerFactory.newInstance();
    Transformer transformer = tf.newTransformer();
    DOMSource source = new DOMSource(document);
    transformer.setOutputProperty(OutputKeys.ENCODING, "UTF-8");
    transformer.setOutputProperty(OutputKeys.INDENT, "yes");
    StringWriter writer = new StringWriter();
    StreamResult result = new StreamResult(writer);
    transformer.transform(source, result);
    String output = writer.getBuffer().toString(); //.replaceAll("\n|\r", "");
    try {
      writer.close();
    } catch (Exception ex) {
    }
    return output;
  }

  /* 生成微信支付sign*/
  public static String createSign(SortedMap<String, String> params, String key) {
    StringBuilder sb = new StringBuilder();
    Set<Map.Entry<String, String>> es = params.entrySet();
    Iterator<Map.Entry<String, String>> it = es.iterator();
    //生成 stringA="appid=wxd930ea5d5a258f4f&body=test&device_info=1000&mch_id=10000100&nonce_str=ibuaiVcKdpRxkhJA";
    while (it.hasNext()) {
      Map.Entry<String, String> entry = (Map.Entry<String, String>) it.next();
      String k = (String) entry.getKey();
      String v = (String) entry.getValue();
      if (null != v && !"".equals(v) && !"sign".equals(k) && !"key".equals(k)) {
        sb.append(k + "=" + v + "&");
      }
    }

    sb.append("key=").append(key);
    String sign = CommonUtils.MD5(sb.toString()).toUpperCase();
    return sign;
  }

  /*校验签名*/
  public static boolean isConrrectSign(SortedMap<String, String> params, String key) {
    String sign = createSign(params, key);
    String weixingPaySign = params.get("sign").toUpperCase();
    return weixingPaySign.equals(sign);
  }

  public static SortedMap<String, String> getSortedMap(Map<String, String> map) {
    TreeMap<String, String> sortedMap = new TreeMap<>();
    Iterator<String> it = map.keySet().iterator();
    while (it.hasNext()) {
      String key = it.next();
      String value = map.get(key);
      String temp = "";
      if (null != value) {
        temp = value.trim();
      }
      sortedMap.put(key, temp);
    }
    return sortedMap;


  }


  /**
   * 日志
   */
  public static Logger getLogger() {
    Logger logger = LoggerFactory.getLogger("wxpay java sdk");
    return logger;
  }


}
